/******************************************************************************
	Cobalt - utility libraries for building XNA games
	Copyright (C) 2008 Philip Djonov

	This program is free software; you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2 of the License, or (at your option)
	any later version.

	This program is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
	for more details.

	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the
	
		Free Software Foundation, Inc.
		51 Franklin Street, Fifth Floor
		Boston, MA  02110-1301, USA.
******************************************************************************/

using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework.Content;

namespace Cobalt.Framework
{

	public sealed class TagsDictionary
	{
		public static readonly TagsDictionary NoTagsDictionary = new TagsDictionary( 0 );
		internal static TagsDictionary ReadTags( ContentReader input )
		{
			int tagCount = input.ReadInt32();

			if( tagCount == 0 )
				return NoTagsDictionary;
			
			TagsDictionary ret = new TagsDictionary( tagCount );

			for( int i = 0; i < tagCount; i++ )
			{
				string name = input.ReadString();
				object value = input.ReadObject<object>();

				ret.tags.Add( name, value );
			}

			return ret;
		}

		public TagsDictionary()
		{
			tags = new Dictionary<string, object>();
		}

		public TagsDictionary( int capacity )
		{
			tags = new Dictionary<string, object>( capacity );
		}

		public TagsDictionary( IEnumerable<KeyValuePair<string, object>> values )
		{
			if( values == null )
				throw new ArgumentNullException( "values" );

			Dictionary<string, object> dict = values as Dictionary<string, object>;
			if( dict != null )
				tags = new Dictionary<string, object>( dict );
			else
			{
				tags = new Dictionary<string, object>();
				foreach( KeyValuePair<string, object> pair in values )
					tags.Add( pair.Key, pair.Value );
			}
		}

		private TagsDictionary( TagsDictionary copySrc )
		{
			tags = new Dictionary<string, object>( copySrc.tags );
		}

		internal Dictionary<string, object> tags;
		public bool TryGetTag<T>( string name, out T value )
		{
			object obj;
			if( tags.TryGetValue( name, out obj ) && obj is T )
			{
				value = (T)obj;
				return true;
			}

			value = default( T );
			return false;
		}

		public T GetTag<T>( string name )
		{
			object obj;
			if( !tags.TryGetValue( name, out obj ) )
				throw new CobaltException( "The tag could not be found." );

			if( !(obj is T) )
				throw new CobaltException( "The tag is not of the desired type." );

			return (T)obj;
		}

		public T GetTag<T>( string name, T defaultValue )
		{
			object obj;
			if( !tags.TryGetValue( name, out obj ) )
				return defaultValue;

			if( !(obj is T) )
				throw new CobaltException( "The tag is not of the desired type." );

			return (T)obj;
		}

		internal TagsDictionary Clone()
		{
			return new TagsDictionary( this );
		}
	}

}